#ifndef OWN_THUNK_STDCALL_TO_STDCALL_H_080327
#define OWN_THUNK_STDCALL_TO_STDCALL_H_080327

#include <Thunk/ThunkBase.h>

#define STD_TO_STD_CODES()				\
/*	POP EAX	*/							\
CONST	CODE_FIRST(byte,POP_EAX,0x58)	\
/*	PUSH m_this	*/						\
CONST	CODE(byte,PUSH,0x68)			\
		CODE(dword_ptr,m_this,0)		\
/*	PUSH EAX	*/						\
CONST	CODE(byte,PUSH_EAX,0x50)		\
/*	JMP m_method(offset)	*/			\
CONST	CODE(byte,JMP,0xE9)				\
CONST	CODE(dword,m_method,0)

namespace Thunk
{
	class StdToStd
	{
	public:

		~StdToStd();
		explicit StdToStd(const void *Obj=0,int method=0);
		StdToStd(const StdToStd &src);
		StdToStd& operator = (const StdToStd &rhs);

		bool operator == (const StdToStd &rhs) const;
		bool operator != (const StdToStd &rhs) const;

		const void* Attach(const void *newObj);
		int Attach(int newMethod);

		template<typename Method>
		int AttachMethod(Method newMethod);

		template<typename Callback>
		Callback MakeCallback() const;

		template<typename Callback>
		operator Callback() const { return MakeCallback<Callback>(); }

	private:

		dword_ptr GetObject() const;
		void SetObject(dword_ptr newObj);

		dword GetMethod() const;
		void SetMethod(dword newMethod);

#pragma pack( push ,1 )
	STD_TO_STD_CODES()
#pragma pack( pop )

	};
	
	template<typename Method>
	int StdToStd::AttachMethod(Method newMethod)
	{
		return Attach( Helper::PointerToInt32(newMethod) );
	}

#pragma warning( push )
#pragma warning( disable : 4311 )
	template<typename Callback>
	Callback StdToStd::MakeCallback() const
	{
		return reinterpret_cast<Callback>( this );
	}
#pragma warning( pop )

}

#endif	//#ifndef OWN_THUNK_STDCALL_TO_STDCALL_H_080327
